﻿using System.Reflection;
using System.Runtime.CompilerServices;

namespace Xioa_UI.Service;

public class ReflectionService
{
    public static BindingFlags BindingFlags =
        BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;

    public static T GetControl<T>(Type type, Object typeInstance, string fieldname)
    {
        var fieldInfo = type.GetField(fieldname, BindingFlags);
        var control = (T)fieldInfo.GetValue(typeInstance);
        return control;
    }

    public static void SetControlValue(Type type, Object typeInstance, string fieldname, object value)
    {
        var fieldInfo = type.GetField(fieldname, BindingFlags);
        fieldInfo.SetValue(typeInstance, value);
    }

    public static EventHandler GetEventHandler(Type type, Object typeInstance, string eventname)
    {
        var method = type.GetMethod(eventname, BindingFlags);
        Delegate del = Delegate.CreateDelegate(typeof(EventHandler), typeInstance, method);
        return del as EventHandler;
    }

    /// <summary>
    /// 用例
    /// </summary>
    /// <typeparam name="T"></typeparam>
    // public static void getMethod<T>()
    // {
    //     BindingFlags flag = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Static;
    //     var f10 = typeof(T).GetMethod("asdhuasdgawydaduasdgu", flag);
    //     var f11 = typeof(Temp).GetMethod("Getbool", flag);
    //     ReflectionService.ReplaceMethod(f10, f11);
    //
    //     var f20 = typeof(T).GetMethod("asdniasnfaksndiqwhawfskhfaiw", flag);
    //     var f21 = typeof(Temp).GetMethod("Getbool1", flag);
    //     ReflectionService.ReplaceMethod(f20, f21);     
    // }
    

    public static void InvokeMethod(Type type, Object typeInstance, string eventname, object[] paramters)
    {
        var method = type.GetMethod(eventname, BindingFlags);
        method?.Invoke(typeInstance, paramters);
    }

    public static void ReplaceMethod(MethodInfo methodToReplace, MethodInfo methodToInject)
    {
        RuntimeHelpers.PrepareMethod(methodToReplace.MethodHandle);
        RuntimeHelpers.PrepareMethod(methodToInject.MethodHandle);

        unsafe
        {
            if (IntPtr.Size == 4)
            {
                int* inj = (int*)methodToInject.MethodHandle.Value.ToPointer() + 2;
                int* tar = (int*)methodToReplace.MethodHandle.Value.ToPointer() + 2;
#if DEBUG
                Console.WriteLine("\nVersion x86 Debug\n");

                byte* injInst = (byte*)*inj;
                byte* tarInst = (byte*)*tar;

                int* injSrc = (int*)(injInst + 1);
                int* tarSrc = (int*)(tarInst + 1);

                *tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
                    Console.WriteLine("\nVersion x86 Release\n");
                    *tar = *inj;
#endif
            }
            else
            {
                long* inj = (long*)methodToInject.MethodHandle.Value.ToPointer() + 1;
                long* tar = (long*)methodToReplace.MethodHandle.Value.ToPointer() + 1;
#if DEBUG
                Console.WriteLine("\nVersion x64 Debug\n");
                byte* injInst = (byte*)*inj;
                byte* tarInst = (byte*)*tar;


                int* injSrc = (int*)(injInst + 1);
                int* tarSrc = (int*)(tarInst + 1);

                *tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
                    Console.WriteLine("\nVersion x64 Release\n");
                    *tar = *inj;
#endif
            }
        }
    }
}